define_extension :build, :_flex_builder_project do
  use(:shell).for(:build) {
    set :build_shell_cmd, "ant"
  }

  module ::Wondercap
  module Extensions
  module FlexBuilderProject
        
    class BuildXmlBuilder
      def initialize(project_name)
        @doc = REXML::Document.new
        @project = REXML::Element.new("project", @doc)
        @project.attributes["name"] = project_name
      end

      def add_taskdef(resource, classpath)
        taskdef = REXML::Element.new("taskdef", @project)
        taskdef.attributes["resource"] = resource
        taskdef.attributes["classpath"] = classpath
      end

      def add_property(name, value)
        property = REXML::Element.new("property", @project)
        property.attributes["name"] = name
        property.attributes["value"] = value
      end

      def add_compc_directive
        @directive = REXML::Element.new("compc", @project)
      end

      def add_mxmlc_directive
        @directive = REXML::Element.new("mxmlc", @project)
      end

      def set_mxml_target_path(path)
        @directive.attributes["file"] = path  
      end

      def set_include_classes(classes)
        @directive.attributes["include-classes"] = classes.join(" ")
      end

      def set_headless(headless)
        @directive.attributes["headless-server"] = (headless ? "true" : "false")
      end

      def set_default_background_color(color)
        @directive.attributes["default-background-color"] = color
      end

      def set_default_frame_rate(rate)
        @directive.attributes["default-frame-rate"] = rate
      end

      def add_source_path(path)
        sp = REXML::Element.new("compiler.source-path", @directive)
        sp.attributes["path-element"] = path
      end

      def set_locale(*locales)
        @directive["locale"] = locales.join("")
      end

      def add_library_path(path)
        library_path = REXML::Element.new("compiler.library-path", @directive)
        library_path.attributes["append"] = true
        library_path.attributes["dir"] = path
        library_path.attributes["includes"] = "*.swc"
      end

      def set_target_player(player_version)
        @directive.attributes["target-player"] = player_version
      end

      def add_load_config(path)
        load_config = REXML::Element.new("load-config", @directive)
        load_config.attributes["filename"] = path
      end

      def set_output(path)
        @directive.attributes["output"] = path
      end

      def write(io)
        @doc.write(io, 3)
      end
    end        
        
  end
  end
  end
  
  task :_patch_flex_project do
    builder = Wondercap::Extensions::FlexBuilderProject::BuildXmlBuilder.new(project_name)
    builder.add_taskdef("flexTasks.tasks", File.join(fetch(:flex_sdk_path), "ant", "lib", "flexTasks.jar"))
    builder.add_property("FLEX_HOME", fetch(:flex_sdk_path))
    builder.add_property("APP_ROOT", revision_build.patched_src_path)
   
    _patch_flex_configure.first.call builder

    builder.add_load_config(File.join(fetch(:flex_sdk_path), "frameworks", fetch(:use_air, false) ? "air-config.xml" : "flex-config.xml"))        
    builder.add_source_path(File.join(revision_build.patched_src_path, fetch(:src_path, "src")))
    assets_path = File.join(revision_build.patched_src_path, fetch(:assets_path, "assets"))
    builder.add_source_path(assets_path) if File.directory?(assets_path)
    builder.set_headless(fetch(:headless, false))
    builder.set_target_player(fetch(:target_flash_player)) if exists?(:target_flash_player)

    search_paths = fetch(:flex_libraries_paths, []).dup
    search_paths << File.join(fetch(:flex_sdk_path), "frameworks/libs")
    search_paths << File.join(fetch(:flex_sdk_path), "frameworks/libs/air") if fetch(:use_air, false)
    search_paths.each { |sp| builder.add_library_path(sp) }

    build_xml_path = File.join(revision_build.patched_src_path, "build.xml")
    open(build_xml_path, "w") { |f| builder.write(f) }
  end
  
  task :patch_sources_for_flex_library do
    # we need to wrap lambda with array here because otherwise it will be evaluated on first access -
    # capistrano won't be able to distinguish it from the block set by "set(:name) do ... end" form
    set :_patch_flex_configure, [lambda { |builder|
      builder.add_compc_directive
      classes = nil
      Dir.chdir(File.join(revision_build.patched_src_path, fetch(:src_path, "src"))) do
        classes = Dir[File.join("**", "*")].inject([]) do |memo, cls|
          if cls =~ /(.*)\.(as|mxml)$/
            memo << $1.gsub(/\//, ".")
          end
          memo
        end
      end
      builder.set_include_classes(classes)

      output_name = fetch(:output_swf_name, "#{project_name}.swc")
      output_path = File.join(revision_build.dist_path, output_name)
      builder.set_output(output_path)
    }]
    _patch_flex_project
  end
  
  task :patch_sources_for_flex_application do
    set :_patch_flex_configure, [lambda { |builder|
      builder.add_mxmlc_directive
      target_path = fetch(:mxml_target, "#{project_name}.mxml")
      target_path = File.join(revision_build.patched_src_path, fetch(:src_path, "src"), target_path)
      builder.set_mxml_target_path target_path
      builder.set_default_frame_rate fetch(:default_frame_rate, 24)
      builder.set_default_background_color fetch(:default_background_color, "0xffffff")

      output_name = fetch(:output_swf_name, "#{project_name}.swf")
      output_path = File.join(revision_build.dist_path, output_name)
      builder.set_output(output_path)
    }]
    _patch_flex_project
  end
end

define_extension :build, :flex_builder_application do
  use(:_flex_builder_project).for(:build)
  
  task :patch_sources do
    execute_previous
    patch_sources_for_flex_application
  end
end

define_extension :build, :flex_builder_library do
  use(:_flex_builder_project).for(:build)
  
  task :patch_sources do
    execute_previous
    patch_sources_for_flex_library
  end
end

define_extension :dependencies, :flex_builder_project do
  set(:build_dependencies) do
    sources
        
    properties_fpath = File.join(revision_build.src_path, ".actionScriptProperties")
    if File.exists?(properties_fpath)
      propertiex_xml = open(properties_fpath, "r") { |f| f.read }

      doc = REXML::Document.new propertiex_xml
      entries = REXML::XPath.match(doc, %q{//libraryPathEntry[@kind='3']/@path})

      deps = entries.inject([]) do |result, entry|
        result << $1 if entry.value =~ /^\/(.+?)\//
        result
      end
      deps
    else
      []
    end          
  end
end